package com.corpgovernment.costcenter.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.corpgovernment.api.costcenter.model.CostCenterParamValidateRequest;
import com.corpgovernment.api.costcenter.model.CostCenterParamValidateResponse;
import com.corpgovernment.api.costcenter.model.GetDepartmentsRequest;
import com.corpgovernment.api.costcenter.model.OrgInfo;
import com.corpgovernment.api.organization.dto.request.ProjectInfoDto;
import com.corpgovernment.api.organization.model.org.OrgInfoVo;
import com.corpgovernment.api.organization.model.project.request.CollectProjectInfoRequest;
import com.corpgovernment.api.organization.model.project.request.GetProjectInfoRequest;
import com.corpgovernment.api.organization.model.project.response.ProjectInfoResponse;
import com.corpgovernment.api.organization.soa.IOrganizationClient;
import com.corpgovernment.api.organization.utils.UuidUtil;
import com.corpgovernment.api.organization.vo.GetOrgTreeRsp;
import com.corpgovernment.common.base.JSONResult;
import com.corpgovernment.common.base.Page;
import com.corpgovernment.common.common.CorpBusinessException;
import com.corpgovernment.common.utils.Null;
import com.corpgovernment.common.utils.ObjectStringTrimUtils;
import com.corpgovernment.costcenter.convert.ProjectInfoConvert;
import com.corpgovernment.costcenter.entity.db.*;
import com.corpgovernment.costcenter.mapper.*;
import com.corpgovernment.costcenter.model.CostCenterUploadExcelInfo;
import com.corpgovernment.costcenter.model.ProjectInfoExcelInsertBo;
import com.corpgovernment.costcenter.model.ProjectInfoUploadExcelInfo;
import com.corpgovernment.costcenter.service.IProjectInfoService;
import com.corpgovernment.costcenter.vo.*;
import com.corpgovernment.organization.constant.OrganizationResponseCodeEnum;
import com.corpgovernment.organization.entity.db.MbOrgEmployeeInfo;
import com.corpgovernment.organization.entity.db.MbOrgInfo;
import com.corpgovernment.organization.enumm.ExcelPostEnum;
import com.corpgovernment.organization.service.IOrganizationEmployeeService;
import com.corpgovernment.organization.service.IOrganizationInfoService;
import com.corpgovernment.organization.util.ExcelUtils;
import com.corpgovernment.organization.util.StrUtils;
import com.corpgovernment.organization.vo.ExcelCreateVO;
import com.corpgovernment.organization.vo.GetOrgTreeRequest;
import com.ctrip.corp.obt.generic.core.context.RequestContext;
import com.ctrip.corp.obt.generic.utils.CollectionUtils;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import com.ctrip.corp.obt.shard.context.PageContext;
import com.ctrip.corp.obt.shard.sql.mybatis.interceptor.pagination.IPage;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import tk.mybatis.mapper.entity.Example;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.corpgovernment.permission.config.PermissionFilter.DATA_PERMISSION_ORG_ID_LIST;

@Slf4j
@Service
public class ProjectInfoServiceImpl implements IProjectInfoService {

    @Autowired
    private MbOrgProjectInfoMapper mbOrgProjectInfoMapper;

    @Autowired
    private MbOrgProjectDepartmentMapper mbOrgProjectDepartmentMapper;

    @Autowired
    private ProjectInfoConvert projectInfoConvert;

    @Autowired
    private IOrganizationInfoService organizationInfoService;

    @Autowired
    private MbOrgProjectInfoUploadDetailMapper mbOrgProjectInfoUploadDetailMapper;

    @Autowired
    private MbOrgProjectInfoUploadMapper mbOrgProjectInfoUploadMapper;

    @Autowired
    private IOrganizationEmployeeService organizationEmployeeService;

    @Autowired
    private ExcelUtils excelUtils;

    @Autowired
    private MbOrgProjectCollectMapper orgProjectCollectMapper;

    @Autowired
    private IOrganizationClient organizationService;

    @Override
    public Integer insert(ProjectInfoVo request) {

        StrUtils.fieldRemoveSpace(request);
        //校验项目编码在公司中唯一
        List<MbOrgProjectInfo> companyIdResultList = this.selectProjectInfoByProjectCode(request.getProjectCode(), request.getCompanyId());
        boolean projectCodeResult = companyIdResultList.stream().filter(e -> !StringUtils.isEmpty(e.getProjectCode())).anyMatch(e -> Objects.equals(e.getProjectCode(), request.getProjectCode()));
        if (projectCodeResult) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.PROJECT_CODE_EXISTS);
        }


        //合并数据
        Map<String, List<OrgInfo>> orgMap = request.getDepartments().stream().filter(item -> StringUtils.isBlank(item.getUid())).collect(Collectors.groupingBy(item -> item.getOrgId()));

        //插入项目数据
        MbOrgProjectInfo mbOrgProjectInfo = projectInfoConvert.convertFromVo(request);
        mbOrgProjectInfo.setCreateTime(new Date());
        mbOrgProjectInfo.setUpdateTime(new Date());
        mbOrgProjectInfoMapper.insert(mbOrgProjectInfo);
        int saveId = mbOrgProjectInfo.getId();
        request.setId(mbOrgProjectInfo.getId());
        List<MbOrgProjectDepartment> departmentList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(request.getDepartments())) {

            for (OrgInfo orgInfo : request.getDepartments()) {
                //选择了整个部门则去掉下面的个人
                if (StringUtils.isNotBlank(orgInfo.getUid())) {
                    List<OrgInfo> orgInfos = orgMap.get(orgInfo.getOrgId());
                    if (!CollectionUtils.isEmpty(orgInfos) && orgInfos.size() > 0) {
                        continue;
                    }
                }

                MbOrgProjectDepartment department = new MbOrgProjectDepartment();
                department.setProjectId(mbOrgProjectInfo.getId());
                department.setOrgId(orgInfo.getOrgId());
                department.setOrgName(orgInfo.getName());
                department.setCreateTime(new Date());
                department.setUpdateTime(new Date());
                department.setUid(orgInfo.getUid());
                departmentList.add(department);
            }
            //插入部门数据
            mbOrgProjectDepartmentMapper.insertList(departmentList);
        }
        return saveId;
    }

    /**
     * 删除项目记录
     *
     * @param request
     * @return
     */
    @Override
    public boolean delete(ProjectInfoDelVo request) {
        this.deleteByPkId(request.getId());
        Example collectExample = new Example(MbOrgProjectCollect.class);
        collectExample.createCriteria().andEqualTo("projectId", request.getId());
        orgProjectCollectMapper.deleteByExample(collectExample);
        return true;
    }

    public boolean deleteByPkId(Integer id){
        MbOrgProjectInfo mbOrgProjectInfo = new MbOrgProjectInfo();
        mbOrgProjectInfo.setIsDelete(Boolean.TRUE);
        mbOrgProjectInfo.setId(id);
        mbOrgProjectInfo.setUpdateTime(new Date());
        return mbOrgProjectInfoMapper.updateByPrimaryKeySelective(mbOrgProjectInfo) > 0;
    }

    /**
     * 分页查询
     *
     * @param request
     * @return
     */
    @Override
    public ProjectInfoPageResponseVo select(ProjectInfoPageVo request) {
        ProjectInfoPageResponseVo response = new ProjectInfoPageResponseVo();
        MbOrgProjectInfo mbOrgProjectInfo = new MbOrgProjectInfo();
        mbOrgProjectInfo.setCompanyId(request.getOrgId());
        mbOrgProjectInfo.setProjectName(request.getKey());
        PageHelper.startPage(request.getCurrentPage(), request.getPageSize());
        List<MbOrgProjectInfo> projectInfos = mbOrgProjectInfoMapper.selectMbOrgProjectInfo(mbOrgProjectInfo);
        PageInfo<MbOrgProjectInfo> pageInfo = new PageInfo<>(projectInfos);
        List<ProjectInfoVo> projectInfoList = new ArrayList<>();
        for (MbOrgProjectInfo info : pageInfo.getList()) {
            ProjectInfoVo projectInfoVo = projectInfoConvert.convertToVo(info);
            Example example = new Example(MbOrgProjectDepartment.class);
            example.createCriteria().andEqualTo("projectId", info.getId());
            List<MbOrgProjectDepartment> departmentList = mbOrgProjectDepartmentMapper.selectByExample(example);
            List<OrgInfo> orgInfos = new ArrayList<>();
            for (MbOrgProjectDepartment department : departmentList) {
                OrgInfo orgInfo = new OrgInfo();
                orgInfo.setName(department.getOrgName());
                orgInfo.setOrgId(department.getOrgId());

                if (StringUtils.isNotBlank(department.getUid())) {
                    MbOrgEmployeeInfo allByUid = organizationEmployeeService.findAllByUid(department.getUid());
                    orgInfo.setUid(department.getUid());
                    if (allByUid != null) {
                        orgInfo.setUserName(allByUid.getName());
                    }
                }
                orgInfos.add(orgInfo);
            }
            projectInfoVo.setDepartments(orgInfos);
            projectInfoList.add(projectInfoVo);
        }
        response.setProjectInfoVoList(projectInfoList);//返回前端结果
        response.setCurrentPage(request.getCurrentPage());
        response.setPageSize(request.getPageSize());
        response.setTotalCount((int) pageInfo.getTotal());
        response.setTotalPage((int) pageInfo.getPages());
        return response;
    }


    /**
     * 查询全部项目
     *
     * @param request
     * @return
     */
    @Override
    public ProjectInfoResponse selectPage(GetProjectInfoRequest request) throws Exception {
        ProjectInfoResponse response = new ProjectInfoResponse();
        log.info("查询项目号当前request为:{}", JsonUtils.toJsonString(request));
        //查询收藏项目号关联表
        Example collectExample = new Example(MbOrgProjectCollect.class);
        collectExample.createCriteria().andEqualTo("uid", request.getLoginUid())
                .andEqualTo("orgId", request.getLoginOrgId());

        List<MbOrgProjectCollect> mbOrgProjectCollects = orgProjectCollectMapper.selectByExample(collectExample);
        List<ProjectInfoResponse.ProjectInfoData> resultCollectProjectInfos = new ArrayList<>();
        log.info("resultCollectProjectInfos:{}", JsonUtils.toJsonString(resultCollectProjectInfos));
        //check非空
        if (!CollectionUtils.isEmpty(mbOrgProjectCollects)) {
            //查询收藏的项目号
            log.info("进入查询收藏的项目流程");
            MbOrgProjectInfo mbOrgProjectInfo = new MbOrgProjectInfo();
            mbOrgProjectInfo.setIds(mbOrgProjectCollects.stream().map(MbOrgProjectCollect::getProjectId).map(Integer::valueOf).collect(Collectors.toList()));
            mbOrgProjectInfo.setValid(request.getValid());
            mbOrgProjectInfo.setValidEndDate(DateUtils.parseDate("3000-12-1", "yyyy-MM-dd"));
            if (StringUtils.isNotBlank(request.getQuery())) {
                mbOrgProjectInfo.setProjectName(request.getQuery());
            }
            List<MbOrgProjectInfo> collectProjectInfos = mbOrgProjectInfoMapper.selectMbOrgProjectInfo(mbOrgProjectInfo);
            log.info("collectProjectInfos:{}", JsonUtils.toJsonString(collectProjectInfos));
            //convert
            for (MbOrgProjectInfo info : collectProjectInfos) {
                ProjectInfoResponse.ProjectInfoData projectInfoData = new ProjectInfoResponse.ProjectInfoData();
                projectInfoData.setId(info.getId());
                projectInfoData.setCompany(info.getCompany());
                projectInfoData.setCompanyId(info.getCompanyId());
                projectInfoData.setProjectCode(info.getProjectCode());
                projectInfoData.setProjectLeader(info.getProjectLeader());
                projectInfoData.setProjectName(info.getProjectName());
                projectInfoData.setValid(info.getValid());
                projectInfoData.setIsCollect(Boolean.TRUE);
                resultCollectProjectInfos.add(projectInfoData);
            }
        }
        log.info("resultCollectProjectInfos:{}", JsonUtils.toJsonString(resultCollectProjectInfos));
        Map<Integer, List<ProjectInfoResponse.ProjectInfoData>> pkMap = resultCollectProjectInfos.stream().collect(Collectors.groupingBy(ProjectInfoResponse.ProjectInfoData::getId));
        List<MbOrgProjectInfo> projectInfos = new ArrayList<>();
        if (CollectionUtils.isEmpty(request.getProjectInfoUserList()) || request.getProjectInfoUserList().size() == 0) {
            log.info("进入外部员工查询流程");
            MbOrgProjectInfo mbOrgProjectInfo = new MbOrgProjectInfo();
            mbOrgProjectInfo.setCompanyId(request.getLoginCorpId());
            mbOrgProjectInfo.setValid(request.getValid());
            mbOrgProjectInfo.setValidEndDate(DateUtils.parseDate("3000-12-1", "yyyy-MM-dd"));
            if (StringUtils.isNotBlank(request.getQuery())) {
                mbOrgProjectInfo.setProjectName(request.getQuery());
            }
            projectInfos = mbOrgProjectInfoMapper.selectMbOrgProjectInfo(mbOrgProjectInfo);
        } else {
            log.info("进入正式员工查询流程");
            //获取出所有组织
            List<String> orgIdList = request.getProjectInfoUserList().stream().map(item -> item.getOrgId()).distinct().collect(Collectors.toList());

            //根据项目和部门得关联表获得当前部门当属于某几个项目
            Example departmentExample = new Example(MbOrgProjectDepartment.class);
            departmentExample.createCriteria().andIn("orgId", orgIdList);
            List<MbOrgProjectDepartment> departments = mbOrgProjectDepartmentMapper.selectByExample(departmentExample);

            List<Integer> selectOrgIds = new ArrayList<>();
            Map<String, List<String>> orgIdMap = request.getProjectInfoUserList().stream().
                    collect(Collectors.groupingBy(GetProjectInfoRequest.ProjectInfoUser::getOrgId,
                            Collectors.mapping(GetProjectInfoRequest.ProjectInfoUser::getUid, Collectors.toList())));
            //过滤 精确到个人的 和 只要公司的
            departments.forEach(item -> {
                List<String> uidList = orgIdMap.get(item.getOrgId());
                if (StringUtils.isBlank(item.getUid())) {
                    //存在说明命中orgId
                    if (!CollectionUtils.isEmpty(uidList)) {
                        selectOrgIds.add(item.getProjectId());
                    }

                } else {
                    //两个uid相等
                    if (uidList.contains(item.getUid())) {
                        selectOrgIds.add(item.getProjectId());
                    }
                }

            });

            if (CollectionUtils.isEmpty(selectOrgIds)) {
                projectInfos = new ArrayList<>();
            } else {
                MbOrgProjectInfo mbOrgProjectInfo = new MbOrgProjectInfo();
                mbOrgProjectInfo.setIds(selectOrgIds);
                mbOrgProjectInfo.setValid(request.getValid());
                mbOrgProjectInfo.setValidEndDate(DateUtils.parseDate("3000-12-1", "yyyy-MM-dd"));
                if (StringUtils.isNotBlank(request.getQuery())) {
                    mbOrgProjectInfo.setProjectName(request.getQuery());
                }
                projectInfos = mbOrgProjectInfoMapper.selectMbOrgProjectInfo(mbOrgProjectInfo);
            }

        }
        log.info("pkMap:{}", JsonUtils.toJsonString(pkMap));
        List<ProjectInfoResponse.ProjectInfoData> projectInfoList = new ArrayList<>();
        for (MbOrgProjectInfo info : projectInfos) {
            List<ProjectInfoResponse.ProjectInfoData> pids = pkMap.get(info.getId());
            if (!CollectionUtils.isEmpty(pids)) {
                continue;
            }
            ProjectInfoResponse.ProjectInfoData projectInfoData = new ProjectInfoResponse.ProjectInfoData();
            projectInfoData.setId(info.getId());
            projectInfoData.setCompany(info.getCompany());
            projectInfoData.setCompanyId(info.getCompanyId());
            projectInfoData.setProjectCode(info.getProjectCode());
            projectInfoData.setProjectLeader(info.getProjectLeader());
            projectInfoData.setProjectName(info.getProjectName());
            projectInfoData.setValid(info.getValid());
            projectInfoData.setIsCollect(Boolean.FALSE);
            projectInfoList.add(projectInfoData);
        }
        resultCollectProjectInfos.addAll(projectInfoList);
        response.setList(resultCollectProjectInfos);
        return response;
    }

    /**
     * 获取部门结构
     *
     * @param request
     * @return
     */
    @Override
    public List<GetOrgTreeRsp> getOrgTree(GetDepartmentsRequest request) {
        //查询组织树
        GetOrgTreeRsp orgTree = organizationInfoService.getOrgTree(new GetOrgTreeRequest(request.getOrgId(), request.getIsSelectUser()));

        List<String> selectList = new ArrayList<>();

        if (Objects.nonNull(request.getId()) && request.getId() > 0) {
            List<MbOrgProjectDepartment> departments = mbOrgProjectInfoMapper.selectByProjectId(request.getId());
            if (!CollectionUtils.isEmpty(departments) && departments.size() > 0) {
                selectList = departments.stream().map(item -> item.getOrgId() + "_" + item.getUid()).collect(Collectors.toList());
            }

        }

        //查询公司已经选中的部门

        //当前记录已选的部门
        //List<String> addDepartments = request.getDepartments();

        if ("T".equals(orgTree.getValid())) {
            orgTree.setValid("F");
        } else {
            orgTree.setValid("T");
        }

        if (selectList.contains(orgTree.getOrgId() + "_")) {
            orgTree.setAdd("T");
        } else {
            orgTree.setAdd("F");
        }

        for (GetOrgTreeRsp childrenTree : orgTree.getChildren()) {
            addDepartmentTag(childrenTree, selectList);
        }
        List<GetOrgTreeRsp> result = new ArrayList<>();
        result.add(orgTree);
        return result;
    }

    /**
     * 获取子公司下所有部门,给已经配置的添加标签
     */
    public void addDepartmentTag(GetOrgTreeRsp orgTree, List<String> selectList) {

        if ("T".equals(orgTree.getValid())) {
            orgTree.setValid("F");
        } else {
            orgTree.setValid("T");
        }

        if (selectList.contains(orgTree.getOrgId() + "_")) {
            orgTree.setAdd("T");
        } else {
            orgTree.setAdd("F");
        }

        if (!CollectionUtils.isEmpty(orgTree.getEmpList())) {
            orgTree.getEmpList().stream().filter(e -> Objects.nonNull(e)).forEach(item -> {
                if (selectList.contains(orgTree.getOrgId() + "_" + item.getUid())) {
                    orgTree.setAdd("T");
                } else {
                    orgTree.setAdd("F");
                }
            });
        }

        if (!CollectionUtils.isEmpty(orgTree.getChildren())) {
            orgTree.getChildren().stream().filter(e -> Objects.nonNull(e)).forEach(
                    e -> {
                        addDepartmentTag(e, selectList);
                    }
            );
        }
    }

    @Override
    public boolean update(ProjectInfoVo request) {

        StrUtils.fieldRemoveSpace(request);
        //校验项目编码在公司中唯一
        List<MbOrgProjectInfo> companyIdResultList = selectProjectInfoByProjectCode(request.getProjectCode(), request.getCompanyId());
        for (MbOrgProjectInfo info : companyIdResultList) {
            if (!info.getId().equals(request.getId()) && !StringUtils.isEmpty(info.getProjectCode()) && info.getProjectCode().equals(request.getProjectCode())) {
                throw new CorpBusinessException(OrganizationResponseCodeEnum.PROJECT_CODE_EXISTS);
            }
        }

//        List<String> orgIdList = request.getDepartments().stream().map(t -> t.getOrgId()).collect(Collectors.toList());
//        Example orgExample = new Example(MbOrgProjectDepartment.class);
//        orgExample.createCriteria().andIn("orgId", orgIdList).andNotEqualTo("projectId", request.getId());
//        List<MbOrgProjectDepartment> departments = mbOrgProjectDepartmentMapper.selectByExample(orgExample);
//        if(!CollectionUtils.isEmpty(departments)){
//            throw new CorpBusinessException(ExceptionCodeEnum.Alert, "部门已经绑定项目");
//        }

        Example updateExample = new Example(MbOrgProjectInfo.class);
        updateExample.createCriteria().andEqualTo("id", request.getId());
        MbOrgProjectInfo mbOrgProjectInfo = projectInfoConvert.convertFromVo(request);
        mbOrgProjectInfoMapper.updateByExampleSelective(mbOrgProjectInfo, updateExample);

        if (Objects.isNull(mbOrgProjectInfo.getValidStartDate()) && Objects.isNull(mbOrgProjectInfo.getValidEndDate())
                && !Objects.isNull(mbOrgProjectInfo.getId())) {
            mbOrgProjectInfoMapper.updateCreateTime(mbOrgProjectInfo.getId());
        }


        //先删除原有数据
        Example deleteExample = new Example(MbOrgProjectDepartment.class);
        deleteExample.createCriteria().andEqualTo("projectId", request.getId());
        mbOrgProjectDepartmentMapper.deleteByExample(deleteExample);

        //合并数据
        Map<String, List<OrgInfo>> orgMap = request.getDepartments().stream().filter(item -> StringUtils.isBlank(item.getUid())).collect(Collectors.groupingBy(item -> item.getOrgId()));


        List<MbOrgProjectDepartment> departmentList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(request.getDepartments())) {

            for (OrgInfo orgInfo : request.getDepartments()) {
                //选择了整个部门则去掉下面的个人
                if (StringUtils.isNotBlank(orgInfo.getUid())) {
                    List<OrgInfo> orgInfos = orgMap.get(orgInfo.getOrgId());
                    if (!CollectionUtils.isEmpty(orgInfos) && orgInfos.size() > 0) {
                        continue;
                    }
                }
                MbOrgProjectDepartment department = new MbOrgProjectDepartment();
                department.setProjectId(mbOrgProjectInfo.getId());
                department.setOrgId(orgInfo.getOrgId());
                department.setOrgName(orgInfo.getName());
                department.setCreateTime(new Date());
                department.setUpdateTime(new Date());
                department.setUid(orgInfo.getUid());
                departmentList.add(department);
            }
            //插入部门数据
            mbOrgProjectDepartmentMapper.insertList(departmentList);
            return true;
        }

        return false;
    }

    @Override
    public List<String> selectCostAndProjectOrgId() {
        return mbOrgProjectInfoMapper.selectCostAndProjectOrgId();
    }

    /**
     * 复制属性，list不可以复制，因为类型不同
     *
     * @param orgTree
     * @param departTree
     * @return void
     */
//    private void copyProperties(GetOrgTreeResponse orgTree, GetDepartTreeResponse departTree) {
//        departTree.setId(orgTree.getId());
//        departTree.setOrgId(orgTree.getOrgId());
//        departTree.setLabel(orgTree.getLabel());
//        departTree.setLevel(orgTree.getLevel());
//        departTree.setValid(orgTree.getValid());
//        departTree.setPid(orgTree.getPid());
//        departTree.setType(orgTree.getType());
//    }

    /**
     * 根据项目名称查询项目记录
     *
     * @param projectName
     * @return
     */
    public List<MbOrgProjectInfo> selectProjectInfoByProjectName(String projectName, String companyId) {
        MbOrgProjectInfo mbOrgProjectInfo = new MbOrgProjectInfo();
        mbOrgProjectInfo.setProjectName(projectName);
        mbOrgProjectInfo.setCompanyId(companyId);
        mbOrgProjectInfo.setIsDelete(Boolean.FALSE);
        return mbOrgProjectInfoMapper.select(mbOrgProjectInfo);
    }

    /**
     * 根据项目编码查询项目记录
     *
     * @param projectCode
     * @return
     */
    public List<MbOrgProjectInfo> selectProjectInfoByProjectCode(String projectCode, String companyId) {
        MbOrgProjectInfo mbOrgProjectInfo = new MbOrgProjectInfo();
        mbOrgProjectInfo.setProjectCode(projectCode);
        mbOrgProjectInfo.setCompanyId(companyId);
        mbOrgProjectInfo.setIsDelete(Boolean.FALSE);
        return mbOrgProjectInfoMapper.select(mbOrgProjectInfo);
    }

    /**
     * 根据公司编号查询项目记录
     *
     * @param companyId
     * @return
     */
    @Override
    public List<MbOrgProjectInfo> selectProjectInfoByCompanyId(String companyId) {
        MbOrgProjectInfo mbOrgProjectInfo = new MbOrgProjectInfo();
        mbOrgProjectInfo.setCompanyId(companyId);
        mbOrgProjectInfo.setIsDelete(Boolean.FALSE);
        List<MbOrgProjectInfo> projectInfoList = mbOrgProjectInfoMapper.select(mbOrgProjectInfo);
        if (CollectionUtils.isEmpty(projectInfoList)) {
            return new ArrayList<>();
        }
        projectInfoList.forEach(item -> {
            Example example = new Example(MbOrgProjectDepartment.class);
            example.createCriteria().andEqualTo("projectId", item.getId());
            List<MbOrgProjectDepartment> departmentList = mbOrgProjectDepartmentMapper.selectByExample(example);
            if (!CollectionUtils.isEmpty(departmentList)) {
                departmentList.forEach(i -> {
                    if (StringUtils.isNotBlank(i.getUid())) {
                        MbOrgEmployeeInfo allByUid = organizationEmployeeService.findAllByUid(i.getUid());
                        if (allByUid != null) {
                            i.setUserName(allByUid.getName());
                        }
                    }
                });
                item.setDepartmentList(departmentList);
            }
        });
        return projectInfoList;
    }


    /**
     * 根据公司编号查询项目记录
     *
     * @param
     * @return
     */
    @Override
    public List<MbOrgProjectInfo> selectProjectInfoByCompanyIds(List<Integer> companyId) {
        Example example = new Example(MbOrgProjectInfo.class);
        example.createCriteria().andIn("id", companyId);
        List<MbOrgProjectInfo> mbOrgProjectInfos = mbOrgProjectInfoMapper.selectByExample(example);

        if (CollectionUtils.isEmpty(mbOrgProjectInfos)) {
            return Collections.emptyList();
        }
        Example exampleDepartment = new Example(MbOrgProjectDepartment.class);
        exampleDepartment.createCriteria().andIn("projectId", mbOrgProjectInfos.stream().map(MbOrgProjectInfo::getId).collect(Collectors.toList()));
        List<MbOrgProjectDepartment> departmentList = mbOrgProjectDepartmentMapper.selectByExample(exampleDepartment);


        Map<String, MbOrgEmployeeInfo> userMap = organizationEmployeeService.listByUids(
                        departmentList.stream().map(MbOrgProjectDepartment::getUid).collect(Collectors.toList()))
                .stream().collect(Collectors.toMap(MbOrgEmployeeInfo::getUid, user -> user, (u1, u2) -> u2));

        Map<Integer, List<MbOrgProjectDepartment>> departmentMap = departmentList.stream().collect(Collectors.groupingBy(MbOrgProjectDepartment::getProjectId));


        mbOrgProjectInfos.forEach(item -> {
            if (CollectionUtils.isNotEmpty(departmentMap.get(item.getId()))) {
                List<MbOrgProjectDepartment> department = departmentMap.get(item.getId()).stream().map(i -> {
                    if (StringUtils.isNotBlank(i.getUid())) {
                        MbOrgEmployeeInfo allByUid = userMap.get(i.getUid());
                        if (allByUid != null) {
                            i.setUserName(allByUid.getName());
                        }
                    }
                    return i;
                }).collect(Collectors.toList());
                item.setDepartmentList(department);
            }
        });
        return mbOrgProjectInfos;
    }

    @Override
    public List<ProjectInfoDto> selectProject(CostCenterParamValidateRequest request) {
//        if (CollectionUtils.isEmpty(request.getProjectNo())) {
//            return Collections.emptyList();
//        }

        Example example = new Example(MbOrgProjectInfo.class);
        example.createCriteria().andEqualTo("isDelete", Boolean.FALSE)
            .andEqualTo("companyId", request.getCorpId()).andEqualTo("valid", true);
        List<MbOrgProjectInfo> mbOrgProjectInfos =
            Optional.ofNullable(mbOrgProjectInfoMapper.selectByExample(example)).orElse(new ArrayList<>());
        if (CollectionUtils.isEmpty(mbOrgProjectInfos)) {
            return Collections.emptyList();
        }

        List<ProjectInfoDto> result = new ArrayList<>(mbOrgProjectInfos.size());
        mbOrgProjectInfos.forEach(item -> {
            ProjectInfoDto projectInfoDto = new ProjectInfoDto();
            projectInfoDto.setProjectCode(item.getProjectCode());
            projectInfoDto.setProjectName(item.getProjectName());
            result.add(projectInfoDto);
        });
        return result;
    }

    @Override
    public List<ProjectInfoDto> getProjectInfoByOrgId(String orgId) {
        List<ProjectInfoDto> projectInfoByOrgId = mbOrgProjectInfoMapper.getProjectInfoByOrgId(orgId);
        return projectInfoByOrgId;
    }

    @Override
    public List<ProjectInfoDto> listProjectInfoByOrgId(List<String> orgIdList) {
        return mbOrgProjectInfoMapper.listProjectInfoByOrgId(orgIdList);
    }

    @Override
    public List<ProjectInfoDto> getProjectByProjectCode(List<String> projectCodes) {
        Example example = new Example(MbOrgProjectInfo.class);
        example.createCriteria().andIn("projectCode", projectCodes).andEqualTo("isDelete", Boolean.FALSE);
        List<MbOrgProjectInfo> mbOrgProjectInfos = Optional.ofNullable(mbOrgProjectInfoMapper.selectByExample(example)).orElse(new ArrayList<>());
        if (CollectionUtils.isEmpty(mbOrgProjectInfos)){
            return Collections.emptyList();
        }

        List<ProjectInfoDto> result = new ArrayList<>(mbOrgProjectInfos.size());
        mbOrgProjectInfos.forEach(item ->{
            ProjectInfoDto projectInfoDto = new ProjectInfoDto();
            projectInfoDto.setProjectCode(item.getProjectCode());
            projectInfoDto.setProjectName(item.getProjectName());
            projectInfoDto.setProjectId(item.getId().toString());
            result.add(projectInfoDto);
        });
        return result;
    }

    @Override
    public List<MbOrgProjectInfo> listByProjectCode(Collection<String> projectCodes) {
        Example example = new Example(MbOrgProjectInfo.class);
        example.createCriteria().andIn("projectCode", projectCodes).andEqualTo("isDelete", Boolean.FALSE);
        return Optional.ofNullable(mbOrgProjectInfoMapper.selectByExample(example)).orElse(new ArrayList<>());
    }

    @Override
    public Map<String, List<ProjectInfoDto>> listProjectInfoByOrgIdNew(List<String> orgIdList) {
        HashMap<String, List<ProjectInfoDto>> map = new HashMap<>();
        if (CollectionUtils.isEmpty(orgIdList)){
            return map;
        }
        Example example = new Example(MbOrgProjectDepartment.class);
        example.createCriteria().andIn("orgId", orgIdList);
        List<MbOrgProjectDepartment> mbOrgProjectDepartmentList = mbOrgProjectDepartmentMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(mbOrgProjectDepartmentList)){
            return map;
        }
        List<Integer> projectIdList = mbOrgProjectDepartmentList.stream().map(MbOrgProjectDepartment::getProjectId).collect(Collectors.toList());
        Example projectExample = new Example(MbOrgProjectInfo.class);
        projectExample.createCriteria().andIn("id", projectIdList).andEqualTo("isDelete", false).andEqualTo("valid", true);
        List<MbOrgProjectInfo> mbOrgProjectInfoList = mbOrgProjectInfoMapper.selectByExample(projectExample);
        if (CollectionUtils.isEmpty(mbOrgProjectInfoList)){
            return map;
        }
        mbOrgProjectInfoList.forEach(e ->{
            MbOrgProjectDepartment mbOrgProjectDepartment = mbOrgProjectDepartmentList.stream().filter(k -> k.getProjectId().equals(e.getId())).findFirst().orElse(null);
            if (Objects.nonNull(mbOrgProjectDepartment)) {
                ProjectInfoDto info = new ProjectInfoDto();
                info.setProjectCode(e.getProjectCode());
                info.setProjectName(e.getProjectName());
                info.setProjectId(e.getId().toString());
                if (Objects.isNull(map.get(mbOrgProjectDepartment.getOrgId()))) {
                    ArrayList<ProjectInfoDto> list = new ArrayList<>();
                    list.add(info);
                    map.put(mbOrgProjectDepartment.getOrgId(), list);
                } else {
                    map.get(mbOrgProjectDepartment.getOrgId()).add(info);
                }
            }
        });
        return map;
    }

    /**
     * 查询全部
     *
     * @return
     */
    public List<MbOrgProjectInfo> selectProjectInfoAll() {
        return mbOrgProjectInfoMapper.selectAll();
    }

    @Override
    public String syncProjectInfoExcel(MultipartFile file, ProjectInfoExcelVo requestVo) {
        if (file == null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.UPLOAD_FILE_IS_NULL);
        }
        if (!file.getOriginalFilename().endsWith(".xls") && !file.getOriginalFilename().endsWith(".xlsx")) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.FILE_FORMAT_ERROR);
        }
        //处理异常数控v
        if (StringUtils.isNotBlank(requestVo.getCorpId()) && requestVo.getCorpId().split(",").length > 1) {
            requestVo.setCorpId(requestVo.getCorpId().split(",")[0]);
        }

        try {
            Workbook workbook = null;

            if (file.getOriginalFilename().endsWith(".xls")) {
                workbook = new HSSFWorkbook(file.getInputStream());
            } else if (file.getOriginalFilename().endsWith(".xlsx")) {
                workbook = new XSSFWorkbook(file.getInputStream());
            }

            //取出第一页
            Sheet sheet = workbook.getSheetAt(0);

            List<ProjectInfoExcelColumnVo> beanListFromExcel = excelUtils.getBeanListFromExcelTwo(sheet, ProjectInfoExcelColumnVo.class);

            beanListFromExcel.forEach(t ->  ObjectStringTrimUtils.allFieldRemoveWarp(t));

            //本次任务号
            String taskNo = UuidUtil.getUUid();
            //校验上传内容
            ProjectInfoUploadExcelInfo excelInfo = this.checkExcelInfo(beanListFromExcel, taskNo, requestVo.getCorpId());
            //组装入库数据
            ProjectInfoExcelInsertBo projectInfoExcelInsertBo = this.assembleInfo(excelInfo, requestVo, taskNo, file.getOriginalFilename());
            MbOrgProjectInfoUpload projectInfoUpload = projectInfoExcelInsertBo.getProjectInfoUpload();
            if(projectInfoUpload.getFiledNumber() > 0){
                projectInfoExcelInsertBo.setMessage(String.format("上传%d条，其中校验未通过%d条，校验失败会全部回滚", projectInfoUpload.getSuccessNumber() + projectInfoUpload.getFiledNumber(),
                        projectInfoUpload.getFiledNumber()));
                // 查询入上传记录表
                mbOrgProjectInfoUploadMapper.insert(projectInfoExcelInsertBo.getProjectInfoUpload());
                if (!CollectionUtils.isEmpty(projectInfoExcelInsertBo.getProjectInfoUploadDetails())) {
                    mbOrgProjectInfoUploadDetailMapper.insertList(projectInfoExcelInsertBo.getProjectInfoUploadDetails());
                }
                return projectInfoExcelInsertBo.getMessage();
            }


            //插入上传信息表
            mbOrgProjectInfoUploadMapper.insert(projectInfoExcelInsertBo.getProjectInfoUpload());
            //插入项目信息表
            saveToDb(projectInfoExcelInsertBo);
            //错误日志表
            List<MbOrgProjectInfoUploadDetail> projectInfoUploadDetails = projectInfoExcelInsertBo.getProjectInfoUploadDetails();
            if (!CollectionUtils.isEmpty(projectInfoUploadDetails)) {
                mbOrgProjectInfoUploadDetailMapper.insertList(projectInfoUploadDetails);
            }
            return projectInfoExcelInsertBo.getMessage();
        } catch (Exception e) {
            log.info("捕获到上传异常:{}", e);
            return "上次失败";
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveToDb(ProjectInfoExcelInsertBo projectInfoExcelInsertBo) {
        List<MbOrgProjectInfo> projectInfos = projectInfoExcelInsertBo.getProjectInfos();
        if (!CollectionUtils.isEmpty(projectInfos)) {
            //存在则先删后增
            for (MbOrgProjectInfo projectInfo : projectInfos) {
                Example example = new Example(MbOrgProjectInfo.class);
                example.createCriteria().andEqualTo("companyId", projectInfo.getCompanyId()).
                        andEqualTo("projectCode", projectInfo.getProjectCode()).
                        andEqualTo("isDelete", Boolean.FALSE);

                List<MbOrgProjectInfo> projectInfoList = mbOrgProjectInfoMapper.selectByExample(example);
                if (CollectionUtils.isNotEmpty(projectInfoList)) {
                    projectInfoList.forEach(item -> {
                        //projectInfo.setOldId(item.getId());
                        //mbOrgProjectInfoMapper.delete(item);
                        projectInfo.setId(item.getId());
                        mbOrgProjectInfoMapper.updateByPrimaryKeySelective(projectInfo);

                        MbOrgProjectDepartment department = new MbOrgProjectDepartment();
                        department.setProjectId(item.getId());
                        mbOrgProjectDepartmentMapper.delete(department);
                    });
                } else {
                    mbOrgProjectInfoMapper.insert(projectInfo);
                }
            }

            List<MbOrgProjectDepartment> mbOrgProjectDepartmentList = new ArrayList<>();
            projectInfos.forEach(item -> {
                item.getDepartmentList().forEach(detail -> detail.setProjectId(item.getId()));
                mbOrgProjectDepartmentList.addAll(item.getDepartmentList());

//                    if (Objects.nonNull(item.getOldId()) && item.getOldId() > 0) {
//                        Example exampleCollect = new Example(MbOrgProjectCollect.class);
//                        exampleCollect.createCriteria().andEqualTo("projectId", item.getOldId());
//
//                        MbOrgProjectCollect collect = new MbOrgProjectCollect();
//                        collect.setProjectId(item.getId().toString());
//                        orgProjectCollectMapper.updateByExampleSelective(collect, exampleCollect);
//                    }
            });
            if(CollectionUtils.isNotEmpty(mbOrgProjectDepartmentList)){
                mbOrgProjectDepartmentMapper.insertList(mbOrgProjectDepartmentList);
            }
        }
    }


    public ProjectInfoExcelInsertBo assembleInfo(ProjectInfoUploadExcelInfo excelInfo, ProjectInfoExcelVo requestVo, String taskNo, String fileName) {
        ProjectInfoExcelInsertBo projectInfoExcelInsertBo = new ProjectInfoExcelInsertBo();
        List<MbOrgProjectInfoUploadDetail> projectInfoUploadDetails = new ArrayList<>();
        List<MbOrgProjectInfo> projectInfos = new ArrayList<>();
        Integer successNumber = 0;
        Integer filedNumber = 0;

        for (ProjectInfoUploadExcelInfo.MbOrgProjectInfoUploadDetailBo uploadInfo : excelInfo.getDetailBos()) {
            //为空则正常入库
            uploadInfo.setTaskNo(taskNo);
            if (StringUtils.isNotBlank(uploadInfo.getFiledReason())) {
                MbOrgProjectInfoUploadDetail mbOrgProjectInfoUploadDetail = new MbOrgProjectInfoUploadDetail();
                mbOrgProjectInfoUploadDetail.setTaskNo(taskNo);
                mbOrgProjectInfoUploadDetail.setProjectName(uploadInfo.getProjectName());
                mbOrgProjectInfoUploadDetail.setProjectCode(uploadInfo.getProjectCode());
                mbOrgProjectInfoUploadDetail.setProjectLeader(uploadInfo.getProjectLeader());
                mbOrgProjectInfoUploadDetail.setFiledReason(uploadInfo.getFiledReason());
                mbOrgProjectInfoUploadDetail.setValidStartDate(uploadInfo.getValidStartDate());
                mbOrgProjectInfoUploadDetail.setValidEndDate(uploadInfo.getValidEndDate());
                mbOrgProjectInfoUploadDetail.setLine(uploadInfo.getLine());  //excel行号从0开始
                projectInfoUploadDetails.add(mbOrgProjectInfoUploadDetail);
                filedNumber++;
            } else {
                MbOrgInfo corpInfo = organizationInfoService.findByBusinessCode(uploadInfo.getBusinessCode());
                MbOrgProjectInfo mbOrgProjectInfo = new MbOrgProjectInfo();
                mbOrgProjectInfo.setCompanyId(corpInfo.getOrgId());
                mbOrgProjectInfo.setCompany(corpInfo.getName());
                if (StringUtils.isNotBlank(uploadInfo.getValidStartDate())) {
                    mbOrgProjectInfo.setValidStartDate(DateUtil.parse(uploadInfo.getValidStartDate(), "yyyy-MM-dd HH:mm:ss"));
                }
                if (StringUtils.isNotBlank(uploadInfo.getValidEndDate())) {
                    mbOrgProjectInfo.setValidEndDate(DateUtil.parse(uploadInfo.getValidEndDate(), "yyyy-MM-dd HH:mm:ss"));
                }
                mbOrgProjectInfo.setUpdateTime(new Date());
                mbOrgProjectInfo.setProjectCode(uploadInfo.getProjectCode());
                mbOrgProjectInfo.setProjectName(uploadInfo.getProjectName());
                mbOrgProjectInfo.setProjectLeader(uploadInfo.getProjectLeader());
                mbOrgProjectInfo.setValid(Boolean.TRUE);
                mbOrgProjectInfo.setIsDelete(Boolean.FALSE);
                mbOrgProjectInfo.setOperatorUid(requestVo.getUid());
                mbOrgProjectInfo.setOperatorName(requestVo.getUserName());
                mbOrgProjectInfo.setTaskNo(taskNo);

                // 适用部门
                List<MbOrgProjectDepartment> departments = new ArrayList<>();
                List<String> applicationDepartmentList = uploadInfo.getApplicationDepartmentList();
                for (int i = 0; i < applicationDepartmentList.size(); i++) {
                    String bussinessNameAndCode = applicationDepartmentList.get(i);
                    MbOrgProjectDepartment department = new MbOrgProjectDepartment();
                    List<MbOrgInfo> mbOrgInfos = excelInfo.getOrgIdGroupMap().get(bussinessNameAndCode);
                    department.setOrgName(mbOrgInfos.get(0).getName());
                    department.setOrgId(mbOrgInfos.get(0).getOrgId());
                    department.setCreateTime(new Date());
                    department.setUpdateTime(new Date());
                    departments.add(department);
                }

                mbOrgProjectInfo.setDepartmentList(departments);
                projectInfos.add(mbOrgProjectInfo);
                successNumber++;
            }
        }
        MbOrgProjectInfoUpload projectInfoUpload = new MbOrgProjectInfoUpload();
        projectInfoUpload.setTaskNo(taskNo);
        projectInfoUpload.setFileName(fileName);
        projectInfoUpload.setCreateTime(new Date());
        projectInfoUpload.setSuccessNumber(successNumber);
        projectInfoUpload.setFiledNumber(filedNumber);
        projectInfoUpload.setOperatorName(requestVo.getUserName());
        projectInfoUpload.setCompanyId(requestVo.getCorpId());

        projectInfoExcelInsertBo.setProjectInfos(projectInfos);
        projectInfoExcelInsertBo.setProjectInfoUploadDetails(projectInfoUploadDetails);
        projectInfoExcelInsertBo.setProjectInfoUpload(projectInfoUpload);

        projectInfoExcelInsertBo.setMessage(String.format("上传%d条，失败%d条", projectInfoUpload.getSuccessNumber() + projectInfoUpload.getFiledNumber(), projectInfoUpload.getFiledNumber()));
        return projectInfoExcelInsertBo;
    }

    public ProjectInfoUploadExcelInfo checkExcelInfo(List<ProjectInfoExcelColumnVo> beanListFromExcel, String taskNo, String corpId) {
        ProjectInfoUploadExcelInfo excelInfo = new ProjectInfoUploadExcelInfo();
        List<ProjectInfoUploadExcelInfo.MbOrgProjectInfoUploadDetailBo> uploadDetails = new ArrayList<>();
        DateTime currentTime = new DateTime();
        for (ProjectInfoExcelColumnVo projectInfoExcelBo : beanListFromExcel) {
            if (StringUtils.isBlank(projectInfoExcelBo.getBusinessCode()) && StringUtils.isBlank(projectInfoExcelBo.getProjectName())) {
                continue;
            }
            StringBuffer errorLog = new StringBuffer();
            ProjectInfoUploadExcelInfo.MbOrgProjectInfoUploadDetailBo uploadDetail = new ProjectInfoUploadExcelInfo.MbOrgProjectInfoUploadDetailBo();
            uploadDetail.setTaskNo(taskNo);
            if (StringUtils.isBlank(projectInfoExcelBo.getBusinessCode())) {
                errorLog.append("组织编码为空;");
            }
            uploadDetail.setBusinessCode(projectInfoExcelBo.getBusinessCode());
            if (StringUtils.isBlank(projectInfoExcelBo.getProjectName())) {
                errorLog.append("项目名称为空;");
            }
            if (StringUtils.isBlank(projectInfoExcelBo.getProjectCode())) {
                errorLog.append("项目编码为空;");
            }
            uploadDetail.setLine(Integer.valueOf(projectInfoExcelBo.getLineNo()));
            uploadDetail.setProjectName(projectInfoExcelBo.getProjectName());
            uploadDetail.setProjectCode(projectInfoExcelBo.getProjectCode());
            uploadDetail.setProjectLeader(projectInfoExcelBo.getProjectLeader());
            uploadDetail.setApplicationDepartmentList(Collections.EMPTY_LIST);
            String applicationDepartment = projectInfoExcelBo.getApplicationDepartment();
            if (applicationDepartment != null && !applicationDepartment.isEmpty()) {
                String[] arrayAppDepart = Pattern.compile("[;；]").split(applicationDepartment);
                List<String> applicationDepartmentList = new ArrayList<>(Arrays.asList(arrayAppDepart));
                uploadDetail.setApplicationDepartmentList(applicationDepartmentList);
            }
            // 项目生效开始时间，项目中心生效结束时间规则：
            // 输入格式为：yyyy-MM-dd HH:mm:ss，例如：2023-10-01 12:23:00
            // 两者都不输入，为立即生效，开始时间为当前时间、结束时间为2123-01-01 00:00:00；
            // 两者都输入，开始时间必须大于当前时间，结束时间必须大于开始时间；
            // 只填写开始时间，结束默认值为 2123-01-01 00:00:00；
            // 只填写结束时间，开始时间默认值为当前系统时间；
            DateTime validStartDate = currentTime;
            DateTime validEndDate =  currentTime;
            try {
                validStartDate = StrUtil.isBlank(projectInfoExcelBo.getValidStartDate()) ? currentTime :
                        cn.hutool.core.date.DateUtil.parse(projectInfoExcelBo.getValidStartDate(), DatePattern.NORM_DATETIME_FORMAT);
            } catch (Exception e) {
                errorLog.append("项目生效开始时间日期格式不正确;");
            }
            try {
                validEndDate = StrUtil.isBlank(projectInfoExcelBo.getValidEndDate()) ?
                        cn.hutool.core.date.DateUtil.parse("2123-01-01 00:00:00", DatePattern.NORM_DATETIME_FORMAT):
                        cn.hutool.core.date.DateUtil.parse(projectInfoExcelBo.getValidEndDate(), DatePattern.NORM_DATETIME_FORMAT);
            } catch (Exception e) {
                errorLog.append("项目生效结束时间日期格式不正确;");
            }
            
            if(validStartDate.isBefore(currentTime)){
                errorLog.append("项目中心生效开始时间必须大于当前时间;");
            }
            if(validEndDate.isBefore(currentTime)){
                errorLog.append("项目中心失效结束时间必须大于当前时间;");
            }
            if(validEndDate.before(validStartDate)){
                errorLog.append("项目中心失效结束时间必须大于开始时间;");
            }
            uploadDetail.setValidStartDate(DateUtil.format(validStartDate, DatePattern.NORM_DATETIME_PATTERN));
            uploadDetail.setValidEndDate(DateUtil.format(validEndDate, DatePattern.NORM_DATETIME_PATTERN));
            uploadDetail.setFiledReason(errorLog.toString());
            uploadDetails.add(uploadDetail);
        }

        List<String> businessCodes = beanListFromExcel.stream().filter(f-> StringUtils.isNotBlank(f.getBusinessCode())).map(ProjectInfoExcelColumnVo::getBusinessCode).collect(Collectors.toList());
        List<MbOrgInfo> mbOrgInfos = organizationInfoService.listCompanyByBusinessCodes(businessCodes);
        List<String> orgIdDataPermissions = (List<String>) RequestContext.getCurrentContext().getContextParams(DATA_PERMISSION_ORG_ID_LIST);

        Map<String, List<ProjectInfoUploadExcelInfo.MbOrgProjectInfoUploadDetailBo>> uploadProjectCodeMap = uploadDetails.stream()
                .filter(item -> StringUtils.isNotBlank(item.getProjectCode())).collect(Collectors.groupingBy(ProjectInfoUploadExcelInfo.MbOrgProjectInfoUploadDetailBo::getProjectCode));


        Map<String, List<MbOrgInfo>> businessCodeGroupMap =
                mbOrgInfos.stream().filter(a -> StringUtils.isNotBlank(a.getBusinessCode()))
                        .collect(Collectors.groupingBy(MbOrgInfo::getBusinessCode));

        Map<String, List<MbOrgInfo>> businessCodeAndNameGroupMap = new HashMap<>();

        uploadDetails.forEach(item -> {
            StringBuilder errorLog = new StringBuilder().append(item.getFiledReason());
            List<MbOrgInfo> departmentOrgInfos = new ArrayList<>();
            if (uploadProjectCodeMap.get(item.getProjectCode()) != null && uploadProjectCodeMap.get(item.getProjectCode()).size() > 1) {
                errorLog.append("Excel存在相同的项目编码;");
            }
            if (!businessCodeGroupMap.containsKey(item.getBusinessCode())) {
                errorLog.append(item.getBusinessCode() + "公司或部门不存在;");

            }else {
                MbOrgInfo mbOrgInfo = businessCodeGroupMap.get(item.getBusinessCode()).get(0);
                if ("F".equals(mbOrgInfo.getValid())) {
                    errorLog.append("公司或部门状态无效;");
                }
                // 校验数据权限
                if(CollectionUtils.isNotEmpty(orgIdDataPermissions) && !orgIdDataPermissions.contains(mbOrgInfo.getOrgId())){
                    errorLog.append("公司不在数据权限范围内;");
                }

                departmentOrgInfos = organizationInfoService.listAllDepartments(mbOrgInfo.getOrgId(), false);
            }

            businessCodeAndNameGroupMap.putAll( departmentOrgInfos.stream().filter(a -> StringUtils.isNotBlank(a.getName()))
                    .collect(Collectors.groupingBy(t -> (Optional.ofNullable(t.getName()).orElse("").concat("/").concat(Optional.ofNullable(t.getBusinessCode()).orElse(""))))));

            checkDepartBusinessCode(businessCodeAndNameGroupMap, item,errorLog);
            if(StringUtils.isNotBlank(errorLog)){
                item.setFiledReason(errorLog.toString());
            }

        });
        excelInfo.setDetailBos(uploadDetails);
        excelInfo.setOrgIdGroupMap(businessCodeAndNameGroupMap);
        return excelInfo;
    }

    private void checkDepartBusinessCode(Map<String, List<MbOrgInfo>> businessCodeAndNameGroupMap, ProjectInfoUploadExcelInfo.MbOrgProjectInfoUploadDetailBo item, StringBuilder errorLog) {
        for (int i = 0; i < item.getApplicationDepartmentList().size(); i++) {
            String departBusinessCodeAndName = item.getApplicationDepartmentList().get(i);
            if(StringUtils.isBlank(departBusinessCodeAndName)){
                continue;
            }
            if(!departBusinessCodeAndName.contains("/")){
                errorLog.append("适用部门格式不正确;");
            }
            if(CollectionUtils.isEmpty(businessCodeAndNameGroupMap)){
                continue;
            }
            if (!businessCodeAndNameGroupMap.containsKey(departBusinessCodeAndName)) {
                errorLog.append("适用部门需为项目所属公司下属部门;");
            }else {
                List<MbOrgInfo> mbOrgInfoList =  businessCodeAndNameGroupMap.get(item.getBusinessCode());
                if(CollectionUtils.isEmpty(mbOrgInfoList)){
                    continue;
                }
                MbOrgInfo mbOrgInfo = mbOrgInfoList.get(0);
                String key = Optional.ofNullable(mbOrgInfo.getName()).orElse("").concat("/").concat(Optional.ofNullable(mbOrgInfo.getBusinessCode()).orElse(""));
                if(!departBusinessCodeAndName.equals(key)){
                    errorLog.append("适用部门需为项目所属公司下属部门;");
                }
            }
        }
    }

    /**
     * 获取每个单元格的数据
     *
     * @param cell   单元格对象
     * @param rowNum 第几行
     * @param index  该行第几个
     * @param book   主要用于关闭流
     * @param isKey  是否为键：true-是，false-不是。 如果解析Json键，值为空时报错；如果不是Json键，值为空不报错
     * @return
     * @throws IOException
     */
    public String getValue(Cell cell, int rowNum, int index, Workbook book, boolean isKey) throws IOException {

        // 空白或空
        if (cell == null || cell.getCellType() == Cell.CELL_TYPE_BLANK) {
            if (isKey) {
                book.close();
                throw new NullPointerException(String.format("the key on row %s index %s is null ", ++rowNum, ++index));
            } else {
                return "";
            }
        }

        // 0. 数字 类型
        if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
            if (HSSFDateUtil.isCellDateFormatted(cell)) {
                Date date = cell.getDateCellValue();
                DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                return df.format(date);
            }
            String val = cell.getNumericCellValue() + "";
            val = val.toUpperCase();
            if (val.contains("E")) {
                val = val.split("E")[0].replace(".", "");
            } else {
                if (val.indexOf(".") > 0) {
                    String[] split = val.split("\\.");
                    if (Integer.parseInt(split[1]) > 0) {
                        return val;
                    }
                    return split[0];
                }
            }
            return val;
        }

        // 1. String类型
        if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
            String val = cell.getStringCellValue();
            if (val == null || val.trim().length() == 0) {
                if (book != null) {
                    book.close();
                }
                return "";
            }
            return val.trim();
        }

        // 2. 公式 CELL_TYPE_FORMULA
        if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
            return cell.getStringCellValue();
        }

        // 4. 布尔值 CELL_TYPE_BOOLEAN
        if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
            return cell.getBooleanCellValue() + "";
        }

        // 5.	错误 CELL_TYPE_ERROR
        return "";
    }

    @Override
    public ProjectUploadInfoPageResponseVo selectUploadInfoPage(ProjectUploadInfoPageRequestVo requestVo) {

        PageHelper.startPage(requestVo.getPageNum(), requestVo.getPageSize());
        List<MbOrgProjectInfoUpload> mbOrgProjectInfoUploads = mbOrgProjectInfoUploadMapper.selectProjectInfoUploadPage(requestVo.getCorpId(), requestVo.getTaskNo());
        ProjectUploadInfoPageResponseVo pageResponseVo = new ProjectUploadInfoPageResponseVo();
        PageInfo pageInfo = new PageInfo<>(mbOrgProjectInfoUploads);
        Page<MbOrgProjectInfoUpload> page = new Page(pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getPages(), pageInfo.getTotal(), mbOrgProjectInfoUploads);
        List<ProjectUploadInfoPageResponseVo.ProjectUploadInfoResponseVo> responseVos = new ArrayList<>();
        page.getList().stream().filter(item -> Objects.nonNull(item)).forEach(item -> {
            ProjectUploadInfoPageResponseVo.ProjectUploadInfoResponseVo responseVo = new ProjectUploadInfoPageResponseVo.ProjectUploadInfoResponseVo();

            Example bbOrgProjectInfoUploadDetail = new Example(MbOrgProjectInfoUploadDetail.class);
            bbOrgProjectInfoUploadDetail.createCriteria().andEqualTo("taskNo",item.getTaskNo());
            MbOrgProjectInfoUploadDetail uploadDetail = mbOrgProjectInfoUploadDetailMapper.selectOneByExample(bbOrgProjectInfoUploadDetail);

            if(uploadDetail ==null){
                responseVo.setTaskNo(item.getTaskNo());
                responseVo.setFileName(item.getFileName());
                responseVo.setSuccessNumber(item.getSuccessNumber());
                responseVo.setFiledNumber(0);
                responseVo.setCountNumber(item.getSuccessNumber() + item.getFiledNumber());
                responseVo.setCompanyId(item.getCompanyId());
                responseVo.setCreateTime(item.getCreateTime());
                responseVo.setOperatorName(item.getOperatorName());
                responseVos.add(responseVo);
                return;
            }

            String errorDetail = uploadDetail.getFiledReason();
            String[] arrayAppDepart = Pattern.compile("[;；]").split(errorDetail);
            List<String> errorList = new ArrayList<>(Arrays.asList(arrayAppDepart));

            responseVo.setTaskNo(item.getTaskNo());
            responseVo.setFileName(item.getFileName());
            responseVo.setSuccessNumber(item.getSuccessNumber());
            responseVo.setFiledNumber(errorList.size());
            responseVo.setCountNumber(item.getSuccessNumber() + item.getFiledNumber());
            responseVo.setCompanyId(item.getCompanyId());
            responseVo.setCreateTime(item.getCreateTime());
            responseVo.setOperatorName(item.getOperatorName());
            responseVos.add(responseVo);
        });

        pageResponseVo.setUploadInfoResponseVos(responseVos);//返回前端结果
        pageResponseVo.setCurrentPage(requestVo.getPageNum());
        pageResponseVo.setPageSize(requestVo.getPageSize());
        pageResponseVo.setTotalCount(Integer.parseInt(pageInfo.getTotal() + ""));
        pageResponseVo.setTotalPage(page.getTotalPage());
        return pageResponseVo;
    }

    @Override
    public ProjectUploadInfoPageResponseVo selectUploadDetailInfoPage(ProjectUploadInfoPageRequestVo requestVo) {
        PageHelper.startPage(requestVo.getPageNum(), requestVo.getPageSize());
        List<MbOrgProjectInfoUploadDetail> projectInfoUploadDetails = mbOrgProjectInfoUploadDetailMapper.selectProjectInfoUploadDetailPage(requestVo.getTaskNo());
        ProjectUploadInfoPageResponseVo pageResponseVo = new ProjectUploadInfoPageResponseVo();
        PageInfo pageInfo = new PageInfo<>(projectInfoUploadDetails);
        Page<MbOrgProjectInfoUploadDetail> page = new Page(pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getPages(), pageInfo.getTotal(), projectInfoUploadDetails);
        List<ProjectUploadInfoPageResponseVo.ProjectUploadDetailInfoResponseVo> responseVos = new ArrayList<>();
        page.getList().stream().filter(item -> Objects.nonNull(item)).forEach(item -> {

            String errorDetail = item.getFiledReason();
            String[] arrayAppDepart = Pattern.compile("[;；]").split(errorDetail);
            List<String> errorList = new ArrayList<>(Arrays.asList(arrayAppDepart));

            for (int i = 0; i < errorList.size(); i++) {
                ProjectUploadInfoPageResponseVo.ProjectUploadDetailInfoResponseVo responseVo = new ProjectUploadInfoPageResponseVo.ProjectUploadDetailInfoResponseVo();
                responseVo.setTaskNo(item.getTaskNo());
                responseVo.setLine(item.getLine());
                responseVo.setFiledReason(errorList.get(i));
                responseVos.add(responseVo);
            }

        });
        pageResponseVo.setUploadDetailInfoResponseVos(responseVos);//返回前端结果
        pageResponseVo.setCurrentPage(requestVo.getPageNum());
        pageResponseVo.setPageSize(requestVo.getPageSize());
        pageResponseVo.setTotalCount(Integer.parseInt(pageInfo.getTotal() + ""));
        pageResponseVo.setTotalPage(page.getTotalPage());
        return pageResponseVo;
    }

    @Override
    public void downloadUploadInfo(String taskNo, HttpServletResponse response) {
        Example uploadDetailExample = new Example(MbOrgProjectInfoUploadDetail.class);
        uploadDetailExample.createCriteria().andEqualTo("taskNo", taskNo);
        List<MbOrgProjectInfoUploadDetail> projectInfoUploadDetails = mbOrgProjectInfoUploadDetailMapper.selectByExample(uploadDetailExample);
        List<ProjectUploadInfoDownloadResponseVo> responseVos = new ArrayList<>();
        projectInfoUploadDetails.forEach(item -> {
            responseVos.add(new ProjectUploadInfoDownloadResponseVo(item.getOrgId(), item.getProjectName(), item.getProjectCode(),
                    item.getProjectLeader(), item.getValidStartDate(), item.getValidEndDate(), item.getLine(), item.getFiledReason()));
        });

        Example uploadExample = new Example(MbOrgProjectInfoUpload.class);
        uploadExample.createCriteria().andEqualTo("taskNo", taskNo);
        List<MbOrgProjectInfoUpload> mbOrgProjectInfoUploads = mbOrgProjectInfoUploadMapper.selectByExample(uploadExample);
        String fileName = "项目同步异常数据";
        ExcelPostEnum excelPostEnum = ExcelPostEnum.xlsx;
        if (CollectionUtils.isEmpty(mbOrgProjectInfoUploads)) {
            fileName = mbOrgProjectInfoUploads.get(0).getFileName().replace(".xls", "").replace(".xlsx", "");

            if (mbOrgProjectInfoUploads.get(0).getFileName().endsWith("xls")) {
                excelPostEnum = ExcelPostEnum.xls;
            }
        }

        ExcelCreateVO<ProjectUploadInfoDownloadResponseVo> vo = ExcelCreateVO.<ProjectUploadInfoDownloadResponseVo>builder()
                .fileName(fileName)
                .dataList(responseVos)
                .postfix(excelPostEnum)
                .cls(ProjectUploadInfoDownloadResponseVo.class)
                .build();
        excelUtils.downloadExcelDocument(response, vo);
    }

    @Override
    public Boolean collectProjectInfo(CollectProjectInfoRequest request) {
        // 参数校验
        if (Objects.isNull(request) || StringUtils.isBlank(request.getProjectId()) || StringUtils.isBlank(request.getActionType())){
            return false;
        }
        if ("add".equals(request.getActionType())) {
            MbOrgProjectCollect collect = new MbOrgProjectCollect();
            collect.setOrgId(request.getOrgId());
            collect.setUid(request.getUid());
            collect.setProjectId(request.getProjectId());
            collect.setDataChangeCreateTime(new Date());
            collect.setDataChangeLastTime(new Date());
            orgProjectCollectMapper.insert(collect);
        } else if ("cancel".equals(request.getActionType())) {
            MbOrgProjectCollect collect = new MbOrgProjectCollect();
            collect.setOrgId(request.getOrgId());
            collect.setUid(request.getUid());
            collect.setProjectId(request.getProjectId());
            orgProjectCollectMapper.delete(collect);
        } else {
            return false;
        }
        return true;
    }

    @Override
    public void downloadProjectInfo(String companyId, HttpServletResponse response) {
        List<MbOrgProjectInfo> projectInfos = this.selectProjectInfoByCompanyId(companyId);
        List<ProjectInfoDownloadResponseVo> responseVos = new ArrayList<>();
        Instant start = Instant.now();
        //修改为并行方法
        projectInfos.parallelStream().forEach(item -> {
            Example example = new Example(MbOrgProjectDepartment.class);
            example.createCriteria().andEqualTo("projectId", item.getId());
            List<MbOrgProjectDepartment> departments = mbOrgProjectDepartmentMapper.selectByExample(example);

            String businessCode = null;

            if (CollectionUtils.isNotEmpty(departments)) {
                List<String> orgIds = departments.stream().map(MbOrgProjectDepartment::getOrgId).collect(Collectors.toList());
                JSONResult<List<OrgInfoVo>> orgInfoByOrgIds = organizationService.findOrgInfoByOrgIds(orgIds);
                if (!orgInfoByOrgIds.isSUCCESS() || orgInfoByOrgIds.getData() == null) {
                    return;
                }
                businessCode = orgInfoByOrgIds.getData().stream().map(OrgInfoVo::getBusinessCode).collect(Collectors.joining(","));
            }

            responseVos.add(new ProjectInfoDownloadResponseVo(businessCode, item.getProjectName(), item.getProjectCode(), item.getProjectLeader(),
                    com.corpgovernment.common.utils.DateUtil.dateToString(item.getValidStartDate()),
                    com.corpgovernment.common.utils.DateUtil.dateToString(item.getValidEndDate())));
        });
        Instant end = Instant.now();
        long elapsedTime = Duration.between(start, end).getSeconds();
        log.info("[downloadProjectInfo]查询db数据集耗时[{}]s",elapsedTime);
        String fileName = "项目信息";
        ExcelPostEnum excelPostEnum = ExcelPostEnum.xlsx;
        ExcelCreateVO<ProjectInfoDownloadResponseVo> vo = ExcelCreateVO.<ProjectInfoDownloadResponseVo>builder()
                .fileName(fileName)
                .dataList(responseVos)
                .postfix(excelPostEnum)
                .cls(ProjectInfoDownloadResponseVo.class)
                .build();
        excelUtils.downloadExcelDocument(response, vo);
    }

    /**
     * 模糊查询
     *
     * @param request
     * @return
     */
    @Override
    public ProjectInfoPageResponseVo queryProjectNameCode(ProjectInfoPageVo request) {
        log.info("模糊查询项目编码及名称,request参数:{}",JsonUtils.toJsonString(request));
        ProjectInfoPageResponseVo response = new ProjectInfoPageResponseVo();
        List<ProjectInfoVo> projectInfoList = new ArrayList<>();

        MbOrgProjectInfo mbOrgProjectInfo = new MbOrgProjectInfo();
        // 查询登录用户的数据权限
        List<String> orgIds = new ArrayList<>();
        if(StrUtil.isNotBlank(request.getQueryType()) && request.getQueryType().equalsIgnoreCase("userPermission")){
            Object dataPermissionOrgIdList = RequestContext.getCurrentContext().getContextParams(DATA_PERMISSION_ORG_ID_LIST);
            // 如果为空则说明是超级管理员，直接查询所有。否则查询对应的数据权限
            if (dataPermissionOrgIdList != null) {
                // assert dataPermissionOrgIdList instanceof List
                orgIds = (List<String>) dataPermissionOrgIdList;
            }

            log.info("查询登录用户的数据权限:{}",JsonUtils.toJsonString(orgIds));
            if(CollectionUtils.isNotEmpty(orgIds)){
                mbOrgProjectInfo.setCompanyIdList(orgIds);
            }
        }
        // FIXME 此处与产品确认，如果dataPermissionOrgIdList为空，那么就认定是超级管理员，那么就查询所有
/*        if(CollectionUtils.isEmpty(orgIds)){
            mbOrgProjectInfo.setCompanyId(request.getOrgId());
        }
        // FIXME 此处应该是之前漏删除的代码（之前已经被上面 if(CollectionUtils.isEmpty(orgIds)){} 逻辑替换。但是替换时候漏了删除该代码）
        mbOrgProjectInfo.setCompanyId(request.getOrgId());*/

        // 使用 Name 接收 key
        mbOrgProjectInfo.setProjectName(request.getKey());
        mbOrgProjectInfo.setValid(true);

        IPage<MbOrgProjectInfo> pageInfo = PageContext.startPage(request.getCurrentPage(), request.getPageSize());
        mbOrgProjectInfoMapper.selectMbOrgProjectInfo(mbOrgProjectInfo);

        for (MbOrgProjectInfo info : pageInfo.getRecords()) {
            // 实体类转换
            ProjectInfoVo projectInfoVo = projectInfoConvert.convertToVo(info);
            projectInfoList.add(projectInfoVo);
        }

        response.setProjectInfoVoList(projectInfoList);// 返回前端结果
        response.setCurrentPage(request.getCurrentPage());
        response.setPageSize(request.getPageSize());
        response.setTotalCount((int)pageInfo.getTotal());
        response.setTotalPage((int)pageInfo.getPages());
        // log.info("项目名称/编号response参数：" + response);
        return response;
    }


    @Override
    public CostCenterParamValidateResponse getProject(CostCenterParamValidateRequest request) {

        CostCenterParamValidateResponse response = new CostCenterParamValidateResponse();

        List<String> orgIdList = request.getOrgId();
        List<MbOrgProjectInfo> projectInfoList = mbOrgProjectInfoMapper.selectByOrgIds(orgIdList);

        // 需要校验对应orgId下的项目中心 <orgId,<code,Set<name>>>
        Map<String, List<CostCenterParamValidateResponse.ProjectInfo>> orgIdProjectInfoMap = CollectionUtils.emptyIfNull(projectInfoList)
                .stream().collect(Collectors.groupingBy(MbOrgProjectInfo::getCompanyId,
                    Collectors.mapping(
                        proj -> {
                            CostCenterParamValidateResponse.ProjectInfo info =
                                new CostCenterParamValidateResponse.ProjectInfo();
                            // 存在项目中心的code为null的情况，也存在code为""的情况，将其都替换为""
                            info.setProjectNo(Null.or(proj.getProjectCode(), ""));
                            info.setProjectName(proj.getProjectName());
                            return info;
                        }, Collectors.toList())));

        Map<String, Map<String, Set<String>>> orgIdProjectMap = CollectionUtils.emptyIfNull(projectInfoList).stream()
            .collect(Collectors.groupingBy(MbOrgProjectInfo::getCompanyId,
                Collectors.groupingBy((MbOrgProjectInfo m) -> Null.or(m.getProjectCode(), ""),
                    Collectors.mapping(MbOrgProjectInfo::getProjectName, Collectors.toSet()))));

        response.setProjectInfoList(
            orgIdProjectInfoMap.values().stream().flatMap(List::stream).collect(Collectors.toList()));
        response.setProjectNo(response.getProjectInfoList().stream()
            .map(CostCenterParamValidateResponse.ProjectInfo::getProjectNo).collect(Collectors.toList()));
        response.setOrgIdProjectInfoMap(orgIdProjectInfoMap);
        response.setOrgIdProjectMap(orgIdProjectMap);
        return response;
    }
}
